using System;
using System.Windows.Forms;
using OhioState.AssetManaged;
using OhioState.Graphics;
using OhioState.Graphics.Proxy;
using OhioState.Math;

namespace ComponentControls
{
    public partial class LightingDialog : Form
    {
        private LightCollectionProxy lightCollectionProxy;
        private MaterialProxy materialProxy;

        public LightingDialog(MaterialProxy materialProxy)
        {
            this.materialProxy = materialProxy;
            this.lightCollectionProxy = materialProxy.LightCollection;

            if (lightCollectionProxy.LightProxies.Count == 0) //don't need dialog for "no lights"
            {
                this.Dispose();
                return;
            }

            InitializeComponent();
            cancelButton.Click += new EventHandler(CancelButtonHandler);
            okButton.Click += new EventHandler(OkButtonHandler);
            applyButton.Click += new EventHandler(ApplyButtonHandler);

            lightControl1.lightChangedEvent += new LightControl.LightChangedDelegate(lightChangedHandler);
            PopulateLightSelectionCombo();
            this.Show();
        }

        private void lightChangedHandler(IAssetManaged managed)
        {
            Camera camera = managed as Camera;
            Matrix4 matrix = camera.GetModelViewMatrix();
            Vector4 vector = new Vector4(0, 0, -1, 0);
            vector = matrix * vector;

            materialProxy.BeginManipulation();
            DirectionalLightProxy directionalLightHandler = 
                (DirectionalLightProxy)materialProxy.LightCollection.LightProxies[listBox1.SelectedIndex];
            directionalLightHandler.Position = vector;
            materialProxy.EndManipulation();

            textBox1.Text = "" + vector.x;
            textBox2.Text = "" + vector.y;
            textBox3.Text = "" + vector.z;
            textBox4.Text = "" + vector.w;
        }

        private void CancelButtonHandler(object sender, EventArgs args)
        {
            this.Hide();
        }

        private void OkButtonHandler(object sender, EventArgs args)
        {
            this.Hide();
        }

        private void ApplyButtonHandler(object sender, EventArgs args)
        {
        }

        private void PopulateLightSelectionCombo()
        {
            foreach (DirectionalLightProxy lightProxy in materialProxy.LightCollection.LightProxies)
            {
                listBox1.Items.Add(lightProxy);
            }
            listBox1.SelectedIndex = 0;
        }

        private Camera tempCamera = new Camera(70, 1, 0.1f, 100);
        private void listBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            DirectionalLightProxy lightProxy = listBox1.SelectedItem as DirectionalLightProxy;
            textBox1.Text = "" + lightProxy.Position.x;
            textBox2.Text = "" + lightProxy.Position.y;
            textBox3.Text = "" + lightProxy.Position.z;
            textBox4.Text = "" + lightProxy.Position.w;

            //set up light control properly for the currently selected light
            //(in other words, light up the sphere properly)
            //lightControl1.Camera.SetModelViewMatrix(new Matrix4());
            tempCamera.SetModelViewMatrix(new Matrix4());

            Vector3 v = new Vector3(-lightProxy.Position.x, -lightProxy.Position.y, -lightProxy.Position.z);
            double alpha = Math.PI / 2 - Math.Acos(new Vector3(0, 1, 0).dot(v));
            //lightControl1.Camera.Rotate((float)-alpha, new Vector3(1, 0, 0));//around x
            tempCamera.Rotate((float)-alpha, new Vector3(1, 0, 0));

            Vector3 projection = new Vector3(v.x, 0, v.z);
            projection.normalize();
            double beta = Math.Acos(new Vector3(1, 0, 0).dot(projection)) - Math.PI/2;
            if (projection.z > 0)
            {
                //lightControl1.Camera.Rotate((float)-beta, new Vector3(0, 1, 0));//around y
                tempCamera.Rotate((float)-beta, new Vector3(0, 1, 0));
            }
            else
            {
                //lightControl1.Camera.Rotate((float)beta - (float)Math.PI, new Vector3(0, 1, 0));//around y
                tempCamera.Rotate((float)beta - (float)Math.PI, new Vector3(0, 1, 0));
            }
            lightControl1.Camera.SetModelViewMatrix(tempCamera.GetModelViewMatrix());
        }

        private void textBox_TextChanged(object sender, EventArgs e)
        {
            int index = 0;
            if (sender == textBox1) index = 0;
            else if (sender == textBox2) index = 1;
            else if (sender == textBox3) index = 2;
            else if (sender == textBox4) index = 3;

            materialProxy.BeginManipulation();
            DirectionalLightProxy directionalLightHandler =
                (DirectionalLightProxy)materialProxy.LightCollection.LightProxies[listBox1.SelectedIndex];
            try
            {
                directionalLightHandler.Position[index] = (float)Convert.ToDouble(((TextBox)sender).Text);
            }
            catch { }
            materialProxy.EndManipulation();
        }

        private void resetButton_Click(object sender, EventArgs e)
        {
            //reset light direction to the default one
            materialProxy.BeginManipulation();
            DirectionalLightProxy directionalLightHandler =
                (DirectionalLightProxy)materialProxy.LightCollection.LightProxies[listBox1.SelectedIndex];

            directionalLightHandler.Position[0] = 0;
            directionalLightHandler.Position[1] = 0;
            directionalLightHandler.Position[2] = -1;
            directionalLightHandler.Position[3] = 0;

            textBox1.Text = "" + directionalLightHandler.Position[0];
            textBox2.Text = "" + directionalLightHandler.Position[1];
            textBox3.Text = "" + directionalLightHandler.Position[2];
            textBox4.Text = "" + directionalLightHandler.Position[3];

            materialProxy.EndManipulation();

            listBoxSelectedIndexChanged(null, null);
        }
    }
}